<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>机器视觉虚拟仿真系统</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <link rel="stylesheet" href="css/common.css">
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }
        .subtitle {
            font-size: 1.3rem;
            opacity: 0.9;
            margin-bottom: 20px;
            color: #a0d2eb;
        }

        .instructions {
            background: rgba(255, 255, 255, 0.08);
            padding: 20px;
            border-radius: 15px;
            margin: 20px 0;
            font-size: 1.05rem;
            line-height: 1.7;
            backdrop-filter: blur(5px);
            border: 1px solid rgba(0, 199, 255, 0.3);
            box-shadow: 0 8px 25px rgba(0, 0, 0, 0.4);
            position: relative;
            overflow: hidden;
            animation: slideInUp 0.8s ease;
        }

        .instructions::before {
            content: "";
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: radial-gradient(circle at top left, rgba(0, 199, 255, 0.1), transparent 70%);
            pointer-events: none;
        }

        .instructions p {
            margin: 12px 0;
            position: relative;
            z-index: 2;
        }

        .highlight {
            color: #00c6ff;
            font-weight: bold;
        }

        .game-info {
            display: flex;
            justify-content: space-between;
            width: 100%;
            max-width: 1200px;
            margin-bottom: 25px;
            gap: 20px;
            animation: fadeIn 1s ease 0.3s both;
        }

        .score-box, .time-box {
            background: rgba(0, 0, 0, 0.25);
            padding: 0 20px;
            border-radius: 15px;
            text-align: center;
            flex: 1;
            display: flex;
            justify-items: center;
            align-items: center;
            justify-content: center;
            backdrop-filter: blur(5px);
            border: 1px solid rgba(0, 199, 255, 0.2);
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
            position: relative;
            overflow: hidden;
            transition: transform 0.3s ease;
        }

        .score-box:hover, .time-box:hover {
            transform: translateY(-5px);
        }

        /*.score-box::before, .time-box::before {*/
        /*    content: "";*/
        /*    position: absolute;*/
        /*    top: 0;*/
        /*    left: 0;*/
        /*    width: 100%;*/
        /*    height: 5px;*/
        /*    background: linear-gradient(to right, #00c6ff, #0072ff);*/
        /*}*/

        .info-title {
            font-size: 1.2rem;
            color: #a0d2eb;
        }

        .score-value {
            font-size: 2.5rem;
            font-weight: bold;
            background: linear-gradient(to right, #00c6ff, #0072ff);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            text-shadow: 0 0 10px rgba(0, 198, 255, 0.3);
        }

        .time-value {
            font-size: 2.5rem;
            font-weight: bold;
            color: #00c6ff;
            text-shadow: 0 0 10px rgba(0, 198, 255, 0.3);
        }
        .info-subtitle{
            margin-left: 20px;
        }

        .game-container {
            display: flex;
            width: 100%;
            max-width: 1200px;
            justify-content: space-between;
            /*margin-bottom: 30px;*/
            background: rgba(255, 255, 255, 0.05);
            border-radius: 15px;
            padding: 25px;
            box-shadow: 0 15px 35px rgba(0, 0, 0, 0.5);
            border: 1px solid rgba(0, 199, 255, 0.2);
            position: relative;
            overflow: hidden;
            z-index: 5;
            animation: zoomIn 0.8s ease;
        }

        .game-container::before {
            content: "";
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: radial-gradient(circle at center, rgba(0, 199, 255, 0.1) 0%, transparent 70%);
            pointer-events: none;
        }

        .components, .images {
            width: 45%;
            min-height: 500px;
            display: flex;
            flex-direction: column;
            justify-content: space-around;
            z-index: 2;
        }

        .components-title, .images-title {
            text-align: center;
            font-size: 1.5rem;
            margin-bottom: 20px;
            color: #00c6ff;
            text-shadow: 0 0 10px rgba(0, 198, 255, 0.5);
            padding: 10px;
            border-bottom: 2px solid rgba(0, 199, 255, 0.3);
        }

        .component-item {
            background: linear-gradient(145deg, rgba(12, 36, 56, 0.8), rgba(8, 25, 40, 0.8));
            border: 2px solid rgba(0, 199, 255, 0.5);
            border-radius: 12px;
            padding: 25px 15px;
            margin: 15px 0;
            cursor: move;
            transition: all 0.3s ease;
            font-size: 1.5rem;
            font-weight: 600;
            text-align: center;
            box-shadow: 0 6px 15px rgba(0, 0, 0, 0.4);
            position: relative;
            overflow: hidden;
            backdrop-filter: blur(5px);
        }

        .component-item:hover {
            transform: translateY(-5px);
            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
            border-color: #00c6ff;
        }

        .component-item::before {
            content: "";
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(0, 199, 255, 0.2), transparent);
            transition: 0.5s;
        }

        .component-item:hover::before {
            left: 100%;
        }

        .image-item {
            background: rgba(255, 255, 255, 0.95);
            border-radius: 12px;
            padding: 10px;
            margin: 10px 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            min-height: 100px;
            box-shadow: 0 6px 15px rgba(0, 0, 0, 0.3);
            transition: all 0.3s ease;
            position: relative;
            overflow: hidden;
            border: 2px solid transparent;
        }
        .image-item.drag-over {
            border: 2px dashed #00c6ff;
            background: rgba(0, 198, 255, 0.1);
            transform: scale(1.02);
        }
        .image-item:hover {
            transform: scale(1.03);
            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.4);
        }

        .image-item img {
            max-width: 100%;
            max-height: 120px;
            object-fit: contain;
        }

        .image-item .img-label {
            font-size: 1rem;
            color: #333;
            font-weight: 500;
            text-align: center;
        }

        .image-item.correct {
            border: 3px solid #2ecc71;
            background: rgba(46, 204, 113, 0.1);
            box-shadow: 0 0 15px rgba(46, 204, 113, 0.3);
        }

        .image-item.incorrect {
            border: 3px solid #e74c3c;
            background: rgba(231, 76, 60, 0.1);
            animation: shake 0.5s;
            box-shadow: 0 0 15px rgba(231, 76, 60, 0.3);
        }

        @keyframes shake {
            0%, 100% { transform: translateX(0); }
            20%, 60% { transform: translateX(-5px); }
            40%, 80% { transform: translateX(5px); }
        }

        .controls {
            display: flex;
            gap: 25px;
            margin: 25px 0;
            flex-wrap: wrap;
            justify-content: center;
            animation: fadeIn 1s ease 0.5s both;
        }

        button {
            background: linear-gradient(to right, #00c6ff, #0072ff);
            color: white;
            border: none;
            padding: 16px 35px;
            font-size: 1.1rem;
            border-radius: 50px;
            cursor: pointer;
            transition: all 0.3s ease;
            font-weight: 600;
            box-shadow: 0 6px 15px rgba(0, 0, 0, 0.3);
            position: relative;
            overflow: hidden;
            z-index: 1;
            min-width: 180px;
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 10px;
        }

        button::before {
            content: "";
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
            transition: 0.5s;
            z-index: -1;
        }

        button:hover {
            transform: translateY(-5px);
            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.4);
        }

        button:hover::before {
            left: 100%;
        }

        button:active {
            transform: translateY(1px);
        }

        .connection-feedback {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: rgba(0, 0, 0, 0.8);
            padding: 20px 40px;
            border-radius: 15px;
            text-align: center;
            font-size: 1.5rem;
            z-index: 100;
            backdrop-filter: blur(10px);
            border: 2px solid rgba(0, 199, 255, 0.5);
            box-shadow: 0 0 30px rgba(0, 199, 255, 0.5);
            min-width: 350px;
            display: none;
            transition: opacity 0.3s ease;
        }

        .feedback-visible {
            display: block;
        }

        .feedback-correct {
            color: #2ecc71;
            border-color: #2ecc71;
            box-shadow: 0 0 30px rgba(46, 204, 113, 0.5);
        }

        .feedback-incorrect {
            color: #e74c3c;
            border-color: #e74c3c;
            box-shadow: 0 0 30px rgba(231, 76, 60, 0.5);
        }

        .line {
            position: absolute;
            background: #3498db;
            height: 3px;
            transform-origin: left center;
            z-index: 1;
        }

        .line.correct {
            background: linear-gradient(to right, #00b09b, #96c93d);
            height: 4px;
            box-shadow: 0 0 10px rgba(46, 204, 113, 0.5);
        }

        .line.incorrect {
            background: linear-gradient(to right, #ff416c, #ff4b2b);
            height: 4px;
            box-shadow: 0 0 10px rgba(231, 76, 60, 0.5);
        }

        .success-message {
            font-size: 2rem;
            font-weight: bold;
            color: #2ecc71;
            text-align: center;
            margin: 20px 0;
            text-shadow: 0 0 15px rgba(46, 204, 113, 0.7);
            animation: pulse 2s infinite;
        }

        @keyframes pulse {
            0% { transform: scale(1); }
            50% { transform: scale(1.05); }
            100% { transform: scale(1); }
        }

        @keyframes fadeIn {
            from { opacity: 0; }
            to { opacity: 1; }
        }

        @keyframes fadeInDown {
            from {
                opacity: 0;
                transform: translateY(-30px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }

        @keyframes slideInUp {
            from {
                opacity: 0;
                transform: translateY(30px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }

        @keyframes zoomIn {
            from {
                opacity: 0;
                transform: scale(0.9);
            }
            to {
                opacity: 1;
                transform: scale(1);
            }
        }
        .drag-ghost {
            position: absolute;
            z-index: 1000;
            pointer-events: none;
            opacity: 0.8;
            transform: translate(-50%, -50%);
            border: 2px dashed #00c6ff;
            background: rgba(0, 198, 255, 0.1);
            border-radius: 12px;
            padding: 25px 15px;
            font-size: 1.5rem;
            font-weight: 600;
            text-align: center;
            box-shadow: 0 6px 15px rgba(0, 0, 0, 0.4);
            backdrop-filter: blur(5px);
        }

        @media (max-width: 900px) {
            .game-container {
                flex-direction: column;
                align-items: center;
            }

            .components, .images {
                width: 90%;
                min-height: auto;
                margin-bottom: 20px;
            }

            h1 {
                font-size: 2.2rem;
            }
        }

        @media (max-width: 600px) {
            .component-item {
                font-size: 1.3rem;
                padding: 20px 10px;
            }

            .controls {
                flex-direction: column;
                gap: 15px;
            }

            button {
                width: 100%;
            }

            h1 {
                font-size: 1.8rem;
            }

            .score-value, .time-value {
                font-size: 2rem;
            }
        }

        .confetti {
            position: absolute;
            width: 10px;
            height: 10px;
            border-radius: 50%;
            pointer-events: none;
            z-index: 1000;
        }
    </style>
</head>
<body>
<div class="header">
    <h1>机器视觉虚拟仿真系统</h1>
</div>


<div class="game-info">
    <div class="score-box">
        <div class="info-title">当前得分：</div>
        <div class="score-value" id="score">0</div>
        <div class="info-subtitle">|&nbsp;&nbsp;满分100分</div>
    </div>

</div>

<div class="game-container" id="game-container">
    <div class="connection-feedback" id="connection-feedback">
        <div id="feedback-text">等待您的连接...</div>
    </div>

    <div class="components">
<!--        <div class="components-title"><i class="fas fa-cogs"></i> 工业相机组件</div>-->
        <div class="component-item" id="light-source" draggable="true">镜头和光源</div>
        <div class="component-item" id="lens" draggable="true">视觉检测整体</div>
        <div class="component-item" id="image-software" draggable="true">图像处理软件</div>
        <div class="component-item" id="processing-unit" draggable="true">数据处理单元</div>
        <div class="component-item" id="inspection-platform" draggable="true">检测平台</div>
    </div>

    <div class="images">
<!--        <div class="images-title"><i class="fas fa-images"></i> 对应组件图片</div>-->
        <div class="image-item" id="img-processing-unit">
            <img src="./img/device/数据处理单元.203.png" alt="数据处理单元">
<!--            <div class="img-label">数据处理单元</div>-->
        </div>
        <div class="image-item" id="img-lens">
            <img src="./img/device/镜头和光源.204.png" alt="镜头和光源">
<!--            <div class="img-label">镜头</div>-->
        </div>
        <div class="image-item" id="img-inspection-platform">
            <img src="./img/device/检测平台.205.png" alt="检测平台">
<!--            <div class="img-label">检测平台</div>-->
        </div>
        <div class="image-item" id="img-image-software">
            <img src="./img/device/图像处理软件.202.png" alt="图像处理软件">
<!--            <div class="img-label">图像处理软件</div>-->
        </div>
        <div class="image-item" id="img-light-source">
            <img src="./img/device/视觉检测整体.207.png" alt="视觉检测整体">
<!--            <div class="img-label">光源</div>-->
        </div>
    </div>
</div>

<div class="controls">
    <button id="reset-btn">
        <i class="fas fa-redo"></i> 重新开始
    </button>
    <button id="hint-btn">
        <i class="fas fa-lightbulb"></i> 显示提示
    </button>
</div>

<script>
    // 组件与图片的对应关系
    const correctPairs = {
        'light-source': 'img-light-source',
        'lens': 'img-lens',
        'image-software': 'img-image-software',
        'processing-unit': 'img-processing-unit',
        'inspection-platform': 'img-inspection-platform'
    };

    // 游戏状态
    let score = 0;
    let connections = 0;
    let gameCompleted = false;
    const feedback = document.getElementById('connection-feedback');
    const feedbackText = document.getElementById('feedback-text');

    // 初始化游戏
    function initGame() {
        score = 0;
        connections = 0;
        gameCompleted = false;

        // 更新UI
        document.getElementById('score').textContent = score;

        // 清除所有连线
        document.querySelectorAll('.line').forEach(line => line.remove());

        // 清除所有图片样式
        document.querySelectorAll('.image-item').forEach(item => {
            item.classList.remove('correct', 'incorrect', 'drag-over');
        });

        // 重置连接记录
        for (const key in userConnections) {
            delete userConnections[key];
        }

        for (const key in lines) {
            delete lines[key];
        }

        // 更新反馈
        showFeedback("等待您的连接...", false);
    }

    // 显示连接反馈
    function showFeedback(message, isCorrect) {
        feedback.classList.add('feedback-visible');

        if (isCorrect === true) {
            feedback.classList.add('feedback-correct');
            feedback.classList.remove('feedback-incorrect');
        } else if (isCorrect === false) {
            feedback.classList.add('feedback-incorrect');
            feedback.classList.remove('feedback-correct');
        } else {
            feedback.classList.remove('feedback-correct', 'feedback-incorrect');
        }

        feedbackText.innerHTML = message;

        // 3秒后隐藏反馈
        setTimeout(() => {
            feedback.classList.remove('feedback-visible');
        }, 3000);
    }

    // 存储用户连接
    const userConnections = {};
    const lines = {};

    // 拖拽功能
    document.querySelectorAll('.component-item').forEach(item => {
        item.addEventListener('dragstart', dragStart);
    });

    document.querySelectorAll('.image-item').forEach(item => {
        item.addEventListener('dragover', dragOver);
        item.addEventListener('drop', drop);
        item.addEventListener('dragenter', dragEnter);
        item.addEventListener('dragleave', dragLeave);
    });

    function dragStart(e) {
        e.dataTransfer.setData('text/plain', e.target.id);

        // 1. 同步创建幽灵元素（不要用setTimeout）
        const ghostElement = document.createElement('div');
        ghostElement.className = 'drag-ghost';
        ghostElement.textContent = e.target.textContent; // 使用当前目标文本

        // 2. 添加到文档中（确保可计算尺寸）
        document.body.appendChild(ghostElement);

        // 3. 设置拖拽图像（核心步骤！）
        const offsetX = ghostElement.offsetWidth / 2; // 水平居中
        const offsetY = ghostElement.offsetHeight / 2; // 垂直居中
        e.dataTransfer.setDragImage(ghostElement, offsetX, offsetY);

        // 4. 立即隐藏原始元素（可选）
        setTimeout(() => {
            e.target.classList.add('dragging');
            const ghost = document.querySelector('.drag-ghost');
            if (ghost) ghost.remove();
        }, 0);
    }

    function dragOver(e) {
        e.preventDefault();
    }

    function dragEnter(e) {
        e.preventDefault();
        e.target.classList.add('drag-over');
    }

    function dragLeave(e) {
        e.target.classList.remove('drag-over');
    }

    function drop(e) {
        if (gameCompleted) return;

        e.preventDefault();
        e.target.classList.remove('drag-over');

        const componentId = e.dataTransfer.getData('text/plain');
        const imageId = e.target.id;

        // 检查是否已经连接
        if (userConnections[componentId]) {
            showFeedback("该组件已经连接过了！", false);
            return;
        }

        // 检查是否正确配对
        if (correctPairs[componentId] === imageId) {
            // 创建连接
            createConnection(componentId, imageId);

            // 增加分数
            score += 20;
            document.getElementById('score').textContent = score;
            connections++;

            // 添加正确样式
            e.target.classList.add('correct');

            // 显示成功消息
            showFeedback(`✓ 连接成功！${document.getElementById(componentId).textContent} → <br>得分 +20！当前得分: ${score}/100`, true);

            // 检查游戏是否完成
            if (score === 100) {
                gameCompleted = true;
                setTimeout(() => {
                    showVictory();
                }, 800);
            }
        } else {
            // 错误连接
            e.target.classList.add('incorrect');
            showFeedback(`✗ 连接错误！请尝试其他图片<br>当前得分: ${score}/100`, false);

            // 移除错误样式
            setTimeout(() => {
                e.target.classList.remove('incorrect');
            }, 1000);
        }

        // 移除拖拽样式
        document.querySelector('.dragging').classList.remove('dragging');
    }

    function createConnection(componentId, imageId) {
        const componentElement = document.getElementById(componentId);
        const imageElement = document.getElementById(imageId);

        // 获取位置信息
        const compRect = componentElement.getBoundingClientRect();
        const imgRect = imageElement.getBoundingClientRect();
        const containerRect = document.getElementById('game-container').getBoundingClientRect();

        // 计算起点和终点
        const startX = compRect.right - containerRect.left;
        const startY = compRect.top + compRect.height / 2 - containerRect.top;
        const endX = imgRect.left - containerRect.left;
        const endY = imgRect.top + imgRect.height / 2 - containerRect.top;

        // 计算线条长度和角度
        const length = Math.sqrt(Math.pow(endX - startX, 2) + Math.pow(endY - startY, 2));
        const angle = Math.atan2(endY - startY, endX - startX) * 180 / Math.PI;

        // 创建线条
        const line = document.createElement('div');
        line.className = 'line correct';
        line.style.width = length + 'px';
        line.style.transform = `rotate(${angle}deg)`;
        line.style.left = startX + 'px';
        line.style.top = startY + 'px';

        // 添加到容器
        document.getElementById('game-container').appendChild(line);

        // 存储连接
        userConnections[componentId] = imageId;
        lines[componentId] = line;
    }

    function showVictory() {
        showFeedback(`
                <div class="success-message">恭喜！满分达成！</div>
                <p><i class="fas fa-trophy"></i> 最终得分: 100/100</p>
                <p><i class="fas fa-star"></i> 您已掌握工业相机所有核心组件！</p>
            `, true);

        createConfetti();
    }

    // 重置功能
    document.getElementById('reset-btn').addEventListener('click', initGame);

    // 提示按钮
    document.getElementById('hint-btn').addEventListener('click', () => {
        const unconnected = Object.keys(correctPairs).filter(id => !userConnections[id]);

        if (unconnected.length > 0) {
            const randomId = unconnected[Math.floor(Math.random() * unconnected.length)];
            const component = document.getElementById(randomId).textContent;
            const image = document.getElementById(correctPairs[randomId]).querySelector('.img-label').textContent;

            showFeedback(`💡 提示：${component} 对应 ${image}<br>当前得分: ${score}/100`, null);
        } else {
            showFeedback(`<span style="color:#2ecc71">您已经连接了所有组件！</span><br>当前得分: ${score}/100`, null);
        }
    });

    // 创建彩色纸屑效果
    function createConfetti() {
        const colors = ['#00c6ff', '#0072ff', '#2ecc71', '#f1c40f', '#9b59b6', '#e74c3c', '#1abc9c'];
        const container = document.body;

        for (let i = 0; i < 150; i++) {
            const confetti = document.createElement('div');
            confetti.className = 'confetti';
            confetti.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
            confetti.style.left = Math.random() * 100 + 'vw';
            confetti.style.top = '-10px';
            confetti.style.opacity = '0';

            container.appendChild(confetti);

            // 动画
            const animation = confetti.animate([
                {
                    transform: 'translateY(0) rotate(0deg)',
                    opacity: 0
                },
                {
                    transform: `translateY(${Math.random() * 100 + 50}vh) rotate(${Math.random() * 360}deg)`,
                    opacity: 1
                },
                {
                    transform: `translateY(${Math.random() * 100 + 150}vh) rotate(${Math.random() * 720}deg)`,
                    opacity: 0
                }
            ], {
                duration: 3000 + Math.random() * 2000,
                easing: 'cubic-bezier(0,0.9,0.57,1)'
            });

            animation.onfinish = () => {
                confetti.remove();
            };
        }
    }

    // 初始化游戏
    window.addEventListener('load', () => {
        initGame();
        // updateCurrentTime();
        // setInterval(updateCurrentTime, 1000);
    });
</script>
</body>
</html>